package com.cennavi.mineplay.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

public class ABUtils {

	public static byte[] intToBytes2(int n) {
		byte[] b = new byte[4];
		for (int i = 0; i < 4; i++) {
			b[i] = (byte) (n >> (24 - i * 8));
		}
		return b;
	}
	
	
	public static byte[] doubleToBytes(double value){
		int v1 = (int)value;
		
		int v2 = (int)((value - v1) * 1000000);
		
		byte[] b = new byte[8];
		for (int i = 0; i < 4; i++) {
			b[i] = (byte) (v1 >> (24 - i * 8));
		}
		
		for (int i = 0; i < 4; i++) {
			b[i+4] = (byte) (v2 >> (24 - i * 8));
		}
		return b;
	}
	

	public static byte[] getABPoint(JdbcTemplate jdbc, String sql) {

		ByteArrayOutputStream abo = new ByteArrayOutputStream();

		try {
			List<Map<String, Object>> list = jdbc.queryForList(sql);

			if (list.size() > 0) {

				String attr = null;

				for (String key : list.get(0).keySet()) {
					if (!"geom".equals(key)) {
						attr = key;
						break;
					}
				}

				for (Map<String, Object> map : list) {

					Geometry geom = new WKTReader().read(map.get("geom")
							.toString());

					Object objValue = map.get(attr);

					double attrValue = 0;

					if (objValue instanceof Integer) {
						attrValue = Double.parseDouble(objValue.toString());
					} else if (objValue instanceof Long) {
						attrValue = Double.parseDouble(objValue.toString());
					} else if (objValue instanceof Double) {
						attrValue = (Double)objValue;
					} else {

						attrValue = ((BigDecimal) map.get(attr)).doubleValue();
					}

					Coordinate c = geom.getCoordinate();

					byte[] x = intToBytes2((int) (c.x * 1000000));
					byte[] y = intToBytes2((int) (c.y * 1000000));
					byte[] z = intToBytes2((int) (attrValue ));

					abo.write(x);
					abo.write(y);
					abo.write(z);

				}

			}
		} catch (DataAccessException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return abo.toByteArray();

	}

	public static byte[] getABOd(JdbcTemplate jdbc, String sql) {

		ByteArrayOutputStream abo = new ByteArrayOutputStream();

		try {
			List<Map<String, Object>> list = jdbc.queryForList(sql);

			if (list.size() > 0) {

				for (Map<String, Object> map : list) {

					Geometry geom = new WKTReader().read(map.get("geom")
							.toString());

					Coordinate[] cs = geom.getCoordinates();
					
					for(Coordinate c:cs){

					byte[] x = intToBytes2((int) (c.x * 1000000));
					byte[] y = intToBytes2((int) (c.y * 1000000));

					abo.write(x);
					abo.write(y);
					}
					
					abo.write(-1);

				}

			}
		} catch (DataAccessException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return abo.toByteArray();

	}
	
	
	
	
	public static byte[] getABOdWithAttr(JdbcTemplate jdbc, String sql,String attr) {

		ByteArrayOutputStream abo = new ByteArrayOutputStream();

		try {
			List<Map<String, Object>> list = jdbc.queryForList(sql);

			if (list.size() > 0) {

				for (Map<String, Object> map : list) {

					Geometry geom = new WKTReader().read(map.get("geom")
							.toString());

					Coordinate[] cs = geom.getCoordinates();
					
//					for(Coordinate c:cs){
					
					Coordinate c = cs[0];

					byte[] x = intToBytes2((int) (c.x * 1000000));
					byte[] y = intToBytes2((int) (c.y * 1000000));

					abo.write(x);
					abo.write(y);
					
					c = cs[1];

					x = intToBytes2((int) (c.x * 1000000));
					y = intToBytes2((int) (c.y * 1000000));

					abo.write(x);
					abo.write(y);
					
					double attrValue = 0;
					
					Object obj = map.get(attr);
					
					if (obj instanceof Integer){
						attrValue = ((Integer)obj) / 1.0;
					}else if (obj instanceof BigDecimal){
						BigDecimal bd = (BigDecimal)obj;
						attrValue = bd.doubleValue();
					}
					else{
						attrValue = (double) obj;
					}
					
					byte[] attrByteValue = doubleToBytes(attrValue);
					
					abo.write(attrByteValue);
//					}
					
					abo.write(-1);

				}

			}
		} catch (DataAccessException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return abo.toByteArray();

	}
	
	
	
	
	
	

	public static byte[] getABLink(JdbcTemplate jdbc, String sql) {

		ByteArrayOutputStream abo = new ByteArrayOutputStream();

		try {
			List<Map<String, Object>> list = jdbc.queryForList(sql);

			for (Map<String, Object> map : list) {

				Geometry geom = new WKTReader()
						.read(map.get("geom").toString());

				Coordinate[] cs = geom.getCoordinates();

				for (Coordinate c : cs) {

					byte[] x = intToBytes2((int) (c.x * 1000000));
					byte[] y = intToBytes2((int) (c.y * 1000000));

					abo.write(x);
					abo.write(y);
				}
				abo.write(-1);
			}

		} catch (DataAccessException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return abo.toByteArray();

	}

}
